home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP07.ZIP / CHAP07 / DATATRAN / DATATRAN.CPP < prev    next >
C/C++ Source or Header  |  1993-04-23  |  8KB  |  345 lines

  1. /*
  2.  * DATATRAN.CPP
  3.  *
  4.  * Transfer data object implemented in a DLL.  This data object will
  5.  * cache specific formats and renderings such that its IDataObject
  6.  * interface could be plopped on the clipboard or used in drag-drop.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #define INITGUIDS
  19. #include "datatran.h"
  20.  
  21.  
  22. //Count number of objects and number of locks.
  23. ULONG       g_cObj=0;
  24. ULONG       g_cLock=0;
  25.  
  26. //Make this global for the data object to create listboxes.
  27. HINSTANCE   g_hInst=NULL;
  28.  
  29.  
  30. /*
  31.  * LibMain
  32.  *
  33.  * Purpose:
  34.  *  DLL-specific entry point called from LibEntry.
  35.  *
  36.  * Parameters:
  37.  *  hInst           HINSTANCE instance of the DLL.
  38.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  39.  *  wHeapSize       WORD byte count of the heap.
  40.  *  lpCmdLine       LPSTR to command line used to start the module.
  41.  *
  42.  * Return Value:
  43.  *  HANDLE          Instance handle of the DLL.
  44.  *
  45.  */
  46.  
  47. HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  48.     , WORD cbHeapSize, LPSTR lpCmdLine)
  49.     {
  50.     if (0!=cbHeapSize)
  51.         UnlockData(0);
  52.  
  53.     g_hInst=hInst;
  54.     return hInst;
  55.     }
  56.  
  57.  
  58.  
  59.  
  60.  
  61. /*
  62.  * WEP
  63.  *
  64.  * Purpose:
  65.  *  Required DLL Exit function.  Does nothing.
  66.  *
  67.  * Parameters:
  68.  *  bSystemExit     BOOL indicating if the system is being shut
  69.  *                  down or the DLL has just been unloaded.
  70.  *
  71.  * Return Value:
  72.  *  void
  73.  *
  74.  */
  75.  
  76. void FAR PASCAL WEP(int bSystemExit)
  77.     {
  78.     return;
  79.     }
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86. /*
  87.  * DllGetClassObject
  88.  *
  89.  * Purpose:
  90.  *  Provides an IClassFactory for a given CLSID that this DLL is
  91.  *  registered to support.  This DLL is placed under the CLSID
  92.  *  in the registration database as the InProcServer.
  93.  *
  94.  * Parameters:
  95.  *  clsID           REFCLSID that identifies the class factory desired.
  96.  *                  Since this parameter is passed this DLL can handle
  97.  *                  any number of objects simply by returning different
  98.  *                  class factories here for different CLSIDs.
  99.  *
  100.  *  riid            REFIID specifying the interface the caller wants
  101.  *                  on the class object, usually IID_ClassFactory.
  102.  *
  103.  *  ppv             LPVOID FAR * in which to return the interface pointer.
  104.  *
  105.  * Return Value:
  106.  *  HRESULT         NOERROR on success, otherwise contains an error SCODE.
  107.  */
  108.  
  109. HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
  110.     , LPVOID FAR *ppv)
  111.     {
  112.     //Check that we can provide the interface
  113.     if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
  114.         return ResultFromScode(E_NOINTERFACE);
  115.  
  116.     *ppv=NULL;
  117.  
  118.     //Check each of the three CLSIDs we support.
  119.     if (IsEqualCLSID(rclsid, CLSID_DataTransferObject))
  120.         *ppv=(LPVOID)new CDataTransferClassFactory();
  121.  
  122.     if (NULL==*ppv)
  123.         return ResultFromScode(E_OUTOFMEMORY);
  124.  
  125.     //Don't forget to AddRef the object through any interface we return
  126.     ((LPUNKNOWN)*ppv)->AddRef();
  127.  
  128.     return NOERROR;
  129.     }
  130.  
  131.  
  132.  
  133.  
  134.  
  135. /*
  136.  * DllCanUnloadNow
  137.  *
  138.  * Purpose:
  139.  *  Answers if the DLL can be freed, that is, if there are no
  140.  *  references to anything this DLL provides.
  141.  *
  142.  * Parameters:
  143.  *  None
  144.  *
  145.  * Return Value:
  146.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  147.  */
  148.  
  149. STDAPI DllCanUnloadNow(void)
  150.     {
  151.     SCODE   sc;
  152.  
  153.     //Our answer is whether there are any object or locks
  154.     sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
  155.     return ResultFromScode(sc);
  156.     }
  157.  
  158.  
  159.  
  160.  
  161. /*
  162.  * ObjectDestroyed
  163.  *
  164.  * Purpose:
  165.  *  Function for the DataObject object to call when it gets destroyed.
  166.  *  Since we're in a DLL we only track the number of objects here
  167.  *  letting DllCanUnloadNow take care of the rest.
  168.  *
  169.  * Parameters:
  170.  *  None
  171.  *
  172.  * Return Value:
  173.  *  None
  174.  */
  175.  
  176. void FAR PASCAL ObjectDestroyed(void)
  177.     {
  178.     g_cObj--;
  179.     return;
  180.     }
  181.  
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * CDataTransferClassFactory::CDataTransferClassFactory
  188.  * CDataTransferClassFactory::~CDataTransferClassFactory
  189.  *
  190.  * Constructor Parameters:
  191.  *  None
  192.  */
  193.  
  194. CDataTransferClassFactory::CDataTransferClassFactory(void)
  195.     {
  196.     m_cRef=0L;
  197.     return;
  198.     }
  199.  
  200.  
  201. CDataTransferClassFactory::~CDataTransferClassFactory(void)
  202.     {
  203.     return;
  204.     }
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211. /*
  212.  * CDataTransferClassFactory::QueryInterface
  213.  * CDataTransferClassFactory::AddRef
  214.  * CDataTransferClassFactory::Release
  215.  */
  216.  
  217. STDMETHODIMP CDataTransferClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  218.     {
  219.     *ppv=NULL;
  220.  
  221.     //Any interface on this object is the object pointer.
  222.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
  223.         *ppv=(LPVOID)this;
  224.  
  225.     /*
  226.      * If we actually assign an interface to ppv we need to AddRef it
  227.      * since we're returning a new pointer.
  228.      */
  229.     if (NULL!=*ppv)
  230.         {
  231.         ((LPUNKNOWN)*ppv)->AddRef();
  232.         return NOERROR;
  233.         }
  234.  
  235.     return ResultFromScode(E_NOINTERFACE);
  236.     }
  237.  
  238.  
  239. STDMETHODIMP_(ULONG) CDataTransferClassFactory::AddRef(void)
  240.     {
  241.     return ++m_cRef;
  242.     }
  243.  
  244.  
  245. STDMETHODIMP_(ULONG) CDataTransferClassFactory::Release(void)
  246.     {
  247.     ULONG           cRefT;
  248.  
  249.     cRefT=--m_cRef;
  250.  
  251.     if (0L==m_cRef)
  252.         delete this;
  253.  
  254.     return cRefT;
  255.     }
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263. /*
  264.  * CDataTransferClassFactory::CreateInstance
  265.  *
  266.  * Purpose:
  267.  *  Instantiates a DataObject object that supports the IDataObject
  268.  *  and IUnknown interfaces.  If the caller asks for a different
  269.  *  interface than these two then we fail.
  270.  *
  271.  * Parameters:
  272.  *  punkOuter       LPUNKNOWN to the controlling IUnknown if we are
  273.  *                  being used in an aggregation.
  274.  *  riid            REFIID identifying the interface the caller desires
  275.  *                  to have for the new object.
  276.  *  ppvObj          LPVOID FAR * in which to store the desired interface
  277.  *                  pointer for the new object.
  278.  *
  279.  * Return Value:
  280.  *  HRESULT         NOERROR if successful, otherwise contains E_NOINTERFACE
  281.  *                  if we cannot support the requested interface.
  282.  */
  283.  
  284. STDMETHODIMP CDataTransferClassFactory::CreateInstance(LPUNKNOWN punkOuter
  285.     , REFIID riid, LPVOID FAR *ppvObj)
  286.     {
  287.     LPCDataObject       pObj;
  288.     HRESULT             hr;
  289.  
  290.     *ppvObj=NULL;
  291.     hr=ResultFromScode(E_OUTOFMEMORY);
  292.  
  293.     //Verify that if there is a controlling unknown it's asking for IUnknown
  294.     if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
  295.         return ResultFromScode(E_NOINTERFACE);
  296.  
  297.     //Create the object telling it the data size to work with
  298.     pObj=new CDataObject(punkOuter, ObjectDestroyed);
  299.  
  300.     if (NULL==pObj)
  301.         return hr;
  302.  
  303.     if (pObj->FInit())
  304.         hr=pObj->QueryInterface(riid, ppvObj);
  305.  
  306.     //Kill the object if initial creation or FInit failed.
  307.     if (FAILED(hr))
  308.         delete pObj;
  309.     else
  310.         g_cObj++;
  311.  
  312.     return hr;
  313.     }
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320. /*
  321.  * CDataTransferClassFactory::LockServer
  322.  *
  323.  * Purpose:
  324.  *  Increments or decrements the lock count of the DLL.  If the lock
  325.  *  count goes to zero and there are no objects, the DLL is allowed
  326.  *  to unload.  See DllCanUnloadNow.
  327.  *
  328.  * Parameters:
  329.  *  fLock           BOOL specifying whether to increment or decrement the
  330.  *                  lock count.
  331.  *
  332.  * Return Value:
  333.  *  HRESULT         NOERROR always.
  334.  */
  335.  
  336. STDMETHODIMP CDataTransferClassFactory::LockServer(BOOL fLock)
  337.     {
  338.     if (fLock)
  339.         g_cLock++;
  340.     else
  341.         g_cLock--;
  342.  
  343.     return NOERROR;
  344.     }
  345.